package com.eight.aspect;

import com.eight.annotation.HasPermission;
import com.eight.execption.NoPermissionException;
import com.eight.util.JWTTool;
import com.eight.util.WebUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.Map;

/**
 * @Description: 验证权限的切面类，用来用户是否有相应的校验
 * @Author: Van.Planifolia
 * @CreateTime: 2023-02-24  08:29
 * @Version: 1.0
 */
@Aspect
@Component
public class PermissionCheck {
    /**
     * 定义切入点，并且标注为当添加自定义注解的作为切入点方法
     */
    @Pointcut("@annotation(com.eight.annotation.HasPermission)")
    public void pointCut() {
    }

    /**
     * 定义一个通知方法，当方法被标入注解的时候会将该方法动态的切入，来验证权限信息
     *
     * @param joinPoint 连接点
     * @return 可以理解为被切入方法的对象
     */
    @Around("pointCut()")
    public Object checkPermission(ProceedingJoinPoint joinPoint) throws Throwable {
        // 首先我们要获取当前方法的注解
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        HasPermission annotation = signature.getMethod().getAnnotation(HasPermission.class);
        // 若有相应的注解就获取token，当前用户的具体权限信息，然后对比注解中的value。
        if (annotation != null) {
            // 注解上标注的权限
            String permission = annotation.value();
            HttpServletRequest request = WebUtils.getRequest();
            // 获取token信息，然后解析出其中的权限List
            assert request != null;
            String token = request.getHeader("token");
            Map<String, Object> tokenMap = JWTTool.analyzeToken(token);
            // 然后调用包含判断，来查看是否确实有这个元素
            List<?> permissions = (List<?>) tokenMap.get("permissions");
            // 并行流来判断是否包含
            if (permissions.parallelStream().anyMatch(permission::equals)) {
                // 若确实包含就证明有权限就继续往下走
                return joinPoint.proceed();
            } else {
                // 若不包含我们直接抛出异常
                throw new NoPermissionException("没有这个权限异常");
            }
        }
        // 若没有这个注解就直接往下走
        return joinPoint.proceed();
    }
}
